package com.blacksea.authserver.aspect;

import com.blacksea.authserver.model.OperationLog;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * LogAspect
 * 日志切面
 *
 * @author blacksea3(jxt) 2021/4/18 12:57
 */
@Component
@Aspect
public class LogAspect {
    public static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);

    private final ObjectMapper objectMapper = new ObjectMapper();
    {
        objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
    }

    @Pointcut("execution(* com.blacksea.authserver.web.controller..*.*(..)) || "
        + "execution(* com.blacksea.authserver.service.manager..*.*(..))"
    )
    public void doLog() {
    }

    @Around("doLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object res = null;
        long time = System.currentTimeMillis();
        try {
            res = joinPoint.proceed();
            time = System.currentTimeMillis() - time;
            return res;
        } finally {
            try {
                addOperationLog(joinPoint, res, time);
            } catch (Exception e) {
                LOGGER.error("日志异常:", e);
            }
        }
    }

    private void addOperationLog(JoinPoint joinPoint, Object res, long time) throws JsonProcessingException {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        OperationLog operationLog = new OperationLog();
        operationLog.setRunTime(time);
        operationLog.setReturnValue(objectMapper.writeValueAsString(res));
        operationLog.setArgs(objectMapper.writeValueAsString(joinPoint.getArgs()));
        operationLog.setCreateTime(new Date());
        operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
        LOGGER.info(operationLog.toString());
    }
}
